package com.lzb.play.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;

import com.lzb.play.R;

/**
 * 钢琴键盘控件
 * 包含7个白键和5个黑键，黑键准确位于两个白键中间
 */
public class PianoKeyboardView extends View {

    private Drawable whiteKeyDrawable;
    private Drawable blackKeyDrawable;
    private Drawable whiteKeyPressedDrawable;
    private Drawable blackKeyPressedDrawable;
    private Drawable whiteKeyBottomImageDrawable;
    private Drawable whiteKeyBottomImagePressedDrawable;
    private Bitmap[] whiteKeyBottomImageBitmaps;
    private Bitmap[] whiteKeyBottomImagePressedBitmaps;

    private Bitmap[] whiteKeyBitmaps;
    private Bitmap[] blackKeyBitmaps;
    private Bitmap[] whiteKeyPressedBitmaps;
    private Bitmap[] blackKeyPressedBitmaps;

    private boolean[] whiteKeyPressed;
    private boolean[] blackKeyPressed;

    private int whiteKeyWidth;
    private int whiteKeyHeight;
    private int blackKeyWidth;
    private int blackKeyHeight;
    private float gapPx;
    private boolean isSetting;

    private static final int WHITE_KEY_COUNT = 7;
    private static final int BLACK_KEY_COUNT = 5;
    private static final float BOTTOM_IMAGE_MARGIN_DP = 62f; // 底部间距

    // 正确的黑键位置：位于白键之间的间隙处
    // 黑键位置对应的白键间隙索引：0-1, 1-2, 3-4, 4-5, 5-6
    private static final int[] BLACK_KEY_GAP_INDICES = {0, 1, 3, 4, 5};

    private static final float GAP_DP = 2.5f;

    private OnPianoKeyListener keyListener;

    public interface OnPianoKeyListener {
        void onWhiteKeyPressed(int keyIndex);

        void onWhiteKeyReleased(int keyIndex);

        void onBlackKeyPressed(int keyIndex);

        void onBlackKeyReleased(int keyIndex);
    }

    public PianoKeyboardView(Context context) {
        super(context);
        init(null);
    }

    public PianoKeyboardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public PianoKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    public void setSetting(boolean setting) {
        isSetting = setting;
    }

    private void init(AttributeSet attrs) {
        whiteKeyPressed = new boolean[WHITE_KEY_COUNT];
        blackKeyPressed = new boolean[BLACK_KEY_COUNT];

        whiteKeyBitmaps = new Bitmap[WHITE_KEY_COUNT];
        blackKeyBitmaps = new Bitmap[BLACK_KEY_COUNT];
        whiteKeyPressedBitmaps = new Bitmap[WHITE_KEY_COUNT];
        blackKeyPressedBitmaps = new Bitmap[BLACK_KEY_COUNT];
        whiteKeyBottomImageBitmaps = new Bitmap[WHITE_KEY_COUNT];
        whiteKeyBottomImagePressedBitmaps = new Bitmap[WHITE_KEY_COUNT];

        gapPx = GAP_DP * getResources().getDisplayMetrics().density;

        if (attrs != null) {
            TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.PianoKeyboardView);
            whiteKeyDrawable = ta.getDrawable(R.styleable.PianoKeyboardView_whiteKeyImage);
            blackKeyDrawable = ta.getDrawable(R.styleable.PianoKeyboardView_blackKeyImage);
            whiteKeyPressedDrawable = ta.getDrawable(R.styleable.PianoKeyboardView_whiteKeyPressedImage);
            blackKeyPressedDrawable = ta.getDrawable(R.styleable.PianoKeyboardView_blackKeyPressedImage);
            whiteKeyBottomImageDrawable = ta.getDrawable(R.styleable.PianoKeyboardView_whiteKeyBottomImage);
            whiteKeyBottomImagePressedDrawable = ta.getDrawable(R.styleable.PianoKeyboardView_whiteKeyBottomImagePressed);
            ta.recycle();
        }

        // 设置默认图片
        if (whiteKeyDrawable == null) {
            whiteKeyDrawable = ContextCompat.getDrawable(getContext(), R.drawable.piano_key_white);
        }
        if (blackKeyDrawable == null) {
            blackKeyDrawable = ContextCompat.getDrawable(getContext(), R.drawable.piano_key_black);
        }
        if (whiteKeyPressedDrawable == null) {
            whiteKeyPressedDrawable = ContextCompat.getDrawable(getContext(), R.drawable.piano_key_white_pressed);
        }
        if (blackKeyPressedDrawable == null) {
            blackKeyPressedDrawable = ContextCompat.getDrawable(getContext(), R.drawable.piano_key_black_pressed);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        // 计算琴键尺寸
        float totalGapWidth = gapPx * (WHITE_KEY_COUNT - 1);
        whiteKeyWidth = (int) ((width - totalGapWidth) / WHITE_KEY_COUNT);
        whiteKeyHeight = height;
        blackKeyWidth = (int) (whiteKeyWidth * 0.65f); // 黑键稍窄一些
        blackKeyHeight = (int) (whiteKeyHeight * 0.37f);

        loadKeyBitmaps();
        setMeasuredDimension(width, height);
    }

    private void loadKeyBitmaps() {
        for (int i = 0; i < WHITE_KEY_COUNT; i++) {
            whiteKeyBitmaps[i] = getScaledBitmap(whiteKeyDrawable, whiteKeyWidth, whiteKeyHeight);
            whiteKeyPressedBitmaps[i] = getScaledBitmap(whiteKeyPressedDrawable, whiteKeyWidth, whiteKeyHeight);
            whiteKeyBottomImageBitmaps[i] = getScaledBitmap(whiteKeyBottomImageDrawable,
                    whiteKeyBottomImageDrawable != null ? whiteKeyBottomImageDrawable.getIntrinsicWidth() : whiteKeyWidth,
                    whiteKeyBottomImageDrawable != null ? whiteKeyBottomImageDrawable.getIntrinsicHeight() : 0);
            whiteKeyBottomImagePressedBitmaps[i] = getScaledBitmap(whiteKeyBottomImagePressedDrawable,
                    whiteKeyBottomImagePressedDrawable != null ? whiteKeyBottomImagePressedDrawable.getIntrinsicWidth() : whiteKeyWidth,
                    whiteKeyBottomImagePressedDrawable != null ? whiteKeyBottomImagePressedDrawable.getIntrinsicHeight() : 0);
        }

        for (int i = 0; i < BLACK_KEY_COUNT; i++) {
            blackKeyBitmaps[i] = getScaledBitmap(blackKeyDrawable, blackKeyWidth, blackKeyHeight);
            blackKeyPressedBitmaps[i] = getScaledBitmap(blackKeyPressedDrawable, blackKeyWidth, blackKeyHeight);
        }
    }

    private Bitmap getScaledBitmap(Drawable drawable, int width, int height) {
        if (drawable == null) return null;

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);
        return bitmap;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        float bottomImageMarginPx = BOTTOM_IMAGE_MARGIN_DP * getResources().getDisplayMetrics().density;

        // 绘制白键（带间隙）
        for (int i = 0; i < WHITE_KEY_COUNT; i++) {
            int left = (int) (i * (whiteKeyWidth + gapPx));
            int top = 0;

            Bitmap bitmap = whiteKeyPressed[i] ? whiteKeyPressedBitmaps[i] : whiteKeyBitmaps[i];
            if (bitmap != null && !bitmap.isRecycled()) {
                canvas.drawBitmap(bitmap, left, top, null);
            }

            // 绘制白键底部图片（根据按下状态切换）
            Bitmap bottomImageBitmap = null;
            if (whiteKeyPressed[i]) {
                bottomImageBitmap = whiteKeyBottomImagePressedBitmaps[i];
            } else {
                bottomImageBitmap = whiteKeyBottomImageBitmaps[i];
            }

            if (bottomImageBitmap != null && !bottomImageBitmap.isRecycled()) {
                int imageWidth = bottomImageBitmap.getWidth();
                int imageHeight = bottomImageBitmap.getHeight();

                // 计算居中位置
                int imageLeft = left + (whiteKeyWidth - imageWidth) / 2;
                int imageTop = (int) (whiteKeyHeight - imageHeight - bottomImageMarginPx);

                if (imageTop >= 0) { // 确保图片不会超出白键范围
                    canvas.drawBitmap(bottomImageBitmap, imageLeft, imageTop, null);
                }
            }
        }

        // 绘制黑键（准确位于两个白键中间）
        for (int i = 0; i < BLACK_KEY_COUNT; i++) {
            int gapIndex = BLACK_KEY_GAP_INDICES[i];

            // 计算间隙的开始位置
            float gapStart = (gapIndex + 1) * whiteKeyWidth + gapIndex * gapPx;

            // 黑键位于间隙的中间
            int left = (int) (gapStart + gapPx / 2 - blackKeyWidth / 2);
            int top = 0;

            Bitmap bitmap = blackKeyPressed[i] ? blackKeyPressedBitmaps[i] : blackKeyBitmaps[i];
            if (bitmap != null && !bitmap.isRecycled()) {
                canvas.drawBitmap(bitmap, left, top, null);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        int action = event.getAction();

        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
            if (isSetting) {
                for (int i = 0; i < WHITE_KEY_COUNT; i++) {
                    float whiteKeyStart = i * (whiteKeyWidth + gapPx);
                    float whiteKeyEnd = whiteKeyStart + whiteKeyWidth;

                    if (x >= whiteKeyStart && x < whiteKeyEnd) {
                        if (keyListener != null) {
                            keyListener.onWhiteKeyPressed(i);
                        }
                        break;
                    }
                }
            } else {
                handleTouch(x, y, true);
            }
        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
            if (isSetting) {

            } else {
                releaseAllKeys();
            }
        }

        return true;
    }

    private void handleTouch(float x, float y, boolean isPressed) {
        // 先检查黑键（优先级更高）
        for (int i = 0; i < BLACK_KEY_COUNT; i++) {
            int gapIndex = BLACK_KEY_GAP_INDICES[i];

            float gapStart = (gapIndex + 1) * whiteKeyWidth + gapIndex * gapPx;
            int left = (int) (gapStart + gapPx / 2 - blackKeyWidth / 2);
            int right = left + blackKeyWidth;

            if (x >= left && x < right && y < blackKeyHeight) {
                if (!blackKeyPressed[i] && isPressed) {
                    blackKeyPressed[i] = true;
                    if (keyListener != null) {
                        keyListener.onBlackKeyPressed(i);
                    }
                }
                return;
            }
        }

        // 再检查白键
        for (int i = 0; i < WHITE_KEY_COUNT; i++) {
            float whiteKeyStart = i * (whiteKeyWidth + gapPx);
            float whiteKeyEnd = whiteKeyStart + whiteKeyWidth;

            if (x >= whiteKeyStart && x < whiteKeyEnd) {
                if (!whiteKeyPressed[i] && isPressed) {
                    whiteKeyPressed[i] = true;
                    if (keyListener != null) {
                        keyListener.onWhiteKeyPressed(i);
                    }
                }
                return;
            }
        }
    }

    private void releaseAllKeys() {
        for (int i = 0; i < WHITE_KEY_COUNT; i++) {
            if (whiteKeyPressed[i]) {
                whiteKeyPressed[i] = false;
                if (keyListener != null) {
                    keyListener.onWhiteKeyReleased(i);
                }
            }
        }

        for (int i = 0; i < BLACK_KEY_COUNT; i++) {
            if (blackKeyPressed[i]) {
                blackKeyPressed[i] = false;
                if (keyListener != null) {
                    keyListener.onBlackKeyReleased(i);
                }
            }
        }

        invalidate();
    }

    public void setWhiteKeyImage(@DrawableRes int resId) {
        whiteKeyDrawable = ContextCompat.getDrawable(getContext(), resId);
        loadKeyBitmaps();
        invalidate();
    }

    public void setBlackKeyImage(@DrawableRes int resId) {
        blackKeyDrawable = ContextCompat.getDrawable(getContext(), resId);
        loadKeyBitmaps();
        invalidate();
    }

    public void setWhiteKeyPressedImage(@DrawableRes int resId) {
        whiteKeyPressedDrawable = ContextCompat.getDrawable(getContext(), resId);
        loadKeyBitmaps();
        invalidate();
    }

    public void setBlackKeyPressedImage(@DrawableRes int resId) {
        blackKeyPressedDrawable = ContextCompat.getDrawable(getContext(), resId);
        loadKeyBitmaps();
        invalidate();
    }

    /**
     * 设置白键底部图片
     *
     * @param resId 图片资源ID
     */
    public void setWhiteKeyBottomImage(@DrawableRes int resId) {
        whiteKeyBottomImageDrawable = ContextCompat.getDrawable(getContext(), resId);
        loadKeyBitmaps();
        invalidate();
    }

    /**
     * 设置白键底部按下图片
     *
     * @param resId 图片资源ID
     */
    public void setWhiteKeyBottomImagePressed(@DrawableRes int resId) {
        whiteKeyBottomImagePressedDrawable = ContextCompat.getDrawable(getContext(), resId);
        loadKeyBitmaps();
        invalidate();
    }

    public void setOnPianoKeyListener(OnPianoKeyListener listener) {
        this.keyListener = listener;
    }

    /**
     * 设置白键的按下状态
     *
     * @param keyIndex 白键索引 (0-6)
     * @param pressed  是否按下
     */
    public void setWhiteKeyPressed(int keyIndex, boolean pressed) {
        if (keyIndex >= 0 && keyIndex < WHITE_KEY_COUNT) {
            whiteKeyPressed[keyIndex] = pressed;
            invalidate();
        }
    }

    /**
     * 设置黑键的按下状态
     *
     * @param keyIndex 黑键索引 (0-4)
     * @param pressed  是否按下
     */
    public void setBlackKeyPressed(int keyIndex, boolean pressed) {
        if (keyIndex >= 0 && keyIndex < BLACK_KEY_COUNT) {
            blackKeyPressed[keyIndex] = pressed;
            invalidate();
        }
    }

    /**
     * 获取白键的按下状态
     *
     * @param keyIndex 白键索引 (0-6)
     * @return 是否按下
     */
    public boolean isWhiteKeyPressed(int keyIndex) {
        return keyIndex >= 0 && keyIndex < WHITE_KEY_COUNT ? whiteKeyPressed[keyIndex] : false;
    }

    /**
     * 获取黑键的按下状态
     *
     * @param keyIndex 黑键索引 (0-4)
     * @return 是否按下
     */
    public boolean isBlackKeyPressed(int keyIndex) {
        return keyIndex >= 0 && keyIndex < BLACK_KEY_COUNT ? blackKeyPressed[keyIndex] : false;
    }

    /**
     * 重置所有按键状态（全部释放）
     */
    public void resetAllKeys() {
        for (int i = 0; i < WHITE_KEY_COUNT; i++) {
            whiteKeyPressed[i] = false;
        }
        for (int i = 0; i < BLACK_KEY_COUNT; i++) {
            blackKeyPressed[i] = false;
        }
        invalidate();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        recycleBitmaps();
    }

    private void recycleBitmaps() {
        for (Bitmap bitmap : whiteKeyBitmaps) {
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
        for (Bitmap bitmap : blackKeyBitmaps) {
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
        for (Bitmap bitmap : whiteKeyPressedBitmaps) {
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
        for (Bitmap bitmap : blackKeyPressedBitmaps) {
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
        for (Bitmap bitmap : whiteKeyBottomImageBitmaps) {
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
        for (Bitmap bitmap : whiteKeyBottomImagePressedBitmaps) {
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
    }
}